﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SlimDX;
using SlimDX.Direct3D11;
using SlimDX.DXGI;
//using FreeImageAPI;
using System.Drawing;


namespace Apparat.Renderables.AssimpMeshInterface
{
    public class TextureManager
    {

        #region Singleton Pattern
        private static TextureManager instance = null;
        public static TextureManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new TextureManager();
                }
                return instance;
            }
        }
        #endregion

        #region Constructor
        private TextureManager() { }
        #endregion

        Dictionary<string, Texture2D> FileTextureDictionary = new Dictionary<string, Texture2D>();
        Dictionary<string, ShaderResourceView> FileShaderResourceViewDictionary = new Dictionary<string, ShaderResourceView>();

        public string GetLast(string source, int tail_length)
        {
            if (tail_length >= source.Length)
                return source;
            return source.Substring(source.Length - tail_length);
        }

        public Texture2D Texture2DFromBitmap(Bitmap bmp)
        {
            Texture2D texture;

            System.Drawing.Imaging.BitmapData bitmapData = bmp.LockBits(
     new Rectangle(0, 0, bmp.Width, bmp.Height),
     System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

            DataStream dataStream = new DataStream(bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, true, false);
            DataRectangle dataRectangle = new DataRectangle(bitmapData.Stride, dataStream);

            try
            {
                //Load the texture
                texture = new Texture2D(DeviceManager.Instance.device, new Texture2DDescription()
                {
                    BindFlags = BindFlags.ShaderResource,
                    CpuAccessFlags = CpuAccessFlags.None,
                    Format = Format.B8G8R8A8_UNorm,
                    OptionFlags = ResourceOptionFlags.None,
                    MipLevels = 1,
                    Usage = ResourceUsage.Immutable,
                    Width = bmp.Width,
                    Height = bmp.Height,
                    ArraySize = 1,
                    SampleDescription = new SampleDescription(1, 0)
                }, dataRectangle);
            }
            finally
            {
                //Free bitmap-access resources
                dataStream.Dispose();
                bmp.UnlockBits(bitmapData);
            }

            return texture;
        }



        public void AddTexture(string path, string fileName)
        {
            try
            {

                if (fileName.Contains("\\"))
                {
                    fileName = System.IO.Path.GetFileName(fileName);
                }

                if (!FileTextureDictionary.ContainsKey(fileName))
                {


                    string fullPath = path + "\\" + fileName;

                    Texture2D texture;
                    string format = GetLast(fileName, 3);

                    texture = Texture2D.FromFile(DeviceManager.Instance.device, fullPath);

                    //if (format == "tga")
                    //{
                    //    FIBITMAP dib = new FIBITMAP();
                    //    dib = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_TARGA, fullPath, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
                    //    Bitmap bmp = FreeImage.GetBitmap(dib);
                    //    bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
                    //    texture = Texture2DFromBitmap(bmp);
                    //}
                    //else
                    //{
                    //    texture = Texture2D.FromFile(DeviceManager.Instance.device, fullPath);
                    //}



                    FileTextureDictionary.Add(fileName, texture);

                    if (!FileShaderResourceViewDictionary.ContainsKey(fileName))
                    {
                        ShaderResourceView textureView = new ShaderResourceView(DeviceManager.Instance.device, texture);
                        FileShaderResourceViewDictionary.Add(fileName, textureView);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        public Texture2D GetTexture(string fileName)
        {
            if (fileName.Contains("\\"))
            {
                fileName = System.IO.Path.GetFileName(fileName);
            }

            if (FileTextureDictionary.ContainsKey(fileName))
            {
                return FileTextureDictionary[fileName];
            }

            return null;
        }

        public ShaderResourceView GetShaderResourceView(string fileName)
        {
            if (fileName.Contains("\\"))
            {
                fileName = System.IO.Path.GetFileName(fileName);
            }

            if (FileShaderResourceViewDictionary.ContainsKey(fileName))
            {
                return FileShaderResourceViewDictionary[fileName];
            }

            return null;
        }
    }
}
